package com.winit.openapi.ums.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

import com.alibaba.fastjson.JSONObject;
import com.winit.common.query.Page;
import com.winit.common.query.Searchable;
import com.winit.common.query.Sort;
import com.winit.common.spi.context.CommandContext;
import com.winit.common.utils.JsonMapper;
import com.winit.erp.spi.warehouse.WarehouseService;
import com.winit.erp.spi.warehouse.command.WarehouseCommand;
import com.winit.erp.spi.warehouse.vo.Warehouse;
import com.winit.openapi.constants.ErrorCode;
import com.winit.openapi.controller.BaseController;
import com.winit.openapi.exception.ApiException;
import com.winit.openapi.model.RequestMsg;
import com.winit.openapi.model.ResponseMsg;
import com.winit.openapi.util.ValidateUtil;
import com.winit.ums.spi.ConsigneeAddressService;
import com.winit.ums.spi.commnad.ConsigneeAddressCommand;
import com.winit.ums.spi.common.EnumConstant;
import com.winit.ums.spi.vo.ConsigneeAddress;
import com.winit.ups.spi.systemrule.CountryService;
import com.winit.ups.spi.systemrule.vo.Country;

/**
 * @author haiqiang.yang 2015-6-25 上午10:22:32
 * @since 1.0
 */
@Controller
@RequestMapping(value = "ums/consigneeAddress")
public class ConsigneeAddressController extends BaseController {

    public static Logger    logger = LoggerFactory.getLogger(ConsigneeAddressController.class);

    @Resource
    ConsigneeAddressService consigneeAddressService;

    @Resource
    CountryService          countryService;

    @Resource
    WarehouseService        warehouseService;
    /**
     * 新增收货地址接口
     * 
     * @param requestMsg
     * @param responseMsg
     * @return
     */
    @RequestMapping(value = "/add")
    public String add(@ModelAttribute RequestMsg requestMsg, @ModelAttribute ResponseMsg responseMsg) {
        Object params = requestMsg.getData();
        JSONObject json = null;
        if (params instanceof JSONObject) {
            json = (JSONObject) params;
            validateAddParams(json);
        } else {
            logger.info("JSON格式错误: {}", json);
            throw new ApiException(ErrorCode.ILLEGAL_JSON_STRING);
        }
        ConsigneeAddressCommand command = JsonMapper.fromJson(json.toString(), ConsigneeAddressCommand.class);
        validateAddCommand(command);
        consigneeAddressService.add(command);
        return SUCCESS;
    }

    /**
     * 修改收货地址接口
     * 
     * @param requestMsg
     * @param responseMsg
     * @return
     */
    @RequestMapping(value = "/update")
    public String update(@ModelAttribute RequestMsg requestMsg, @ModelAttribute ResponseMsg responseMsg) {
        Object params = requestMsg.getData();
        JSONObject json = null;
        if (params instanceof JSONObject) {
            json = (JSONObject) params;
            validateUpdateParams(json);
        } else {
            logger.info("JSON格式错误: {}", json);
            throw new ApiException(ErrorCode.ILLEGAL_JSON_STRING);
        }
        ConsigneeAddressCommand command = JsonMapper.fromJson(json.toString(), ConsigneeAddressCommand.class);
        validateUpdateCommand(command);
        consigneeAddressService.update(command);
        return SUCCESS;
    }

    @RequestMapping(value = "/delete")
    public String delete(@ModelAttribute RequestMsg requestMsg, @ModelAttribute ResponseMsg responseMsg) {
        Object params = requestMsg.getData();
        JSONObject json = null;
        if (params instanceof JSONObject) {
            json = (JSONObject) params;
            ValidateUtil.validMaxLength(json, "code", 64, true);
        } else {
            logger.info("JSON格式错误: {}", json);
            throw new ApiException(ErrorCode.ILLEGAL_JSON_STRING);
        }
        ConsigneeAddressCommand command = JsonMapper.fromJson(json.toString(), ConsigneeAddressCommand.class);
        ConsigneeAddress address = consigneeAddressService.get(command.getId());
        
        if (address == null) {
            logger.info("地址不存在: {}", command);
            throw new ApiException(ErrorCode.CONSIGNEE_ADDRESS_NOT_EXISIT, command.getId());
        }

        // 校验该记录是否属于当前用户
        long userId = Long.parseLong(CommandContext.getContext().getUserId());
        if (userId != address.getUserId()) {
            logger.info("地址不属于本人，不允许删除: {}", command);
            throw new ApiException(ErrorCode.RECORD_NOT_BELONG_CURRENT_USER, command.getId());
        }
        consigneeAddressService.delete(command);
        return SUCCESS;
    }

    /**
     * 多条件查询，分页
     * 
     * @param requestMsg
     * @param responseMsg
     * @return
     */
    @RequestMapping(value = "/query")
    public String query(@ModelAttribute RequestMsg requestMsg, @ModelAttribute ResponseMsg responseMsg) {
        ConsigneeAddressCommand command = new ConsigneeAddressCommand();
        Searchable<?> searchable = Searchable.newSearchable();
        searchable.addSort(new Sort(Sort.Direction.DESC, "ID"));
        Object params = requestMsg.getData();
        JSONObject json = null;
        if (params instanceof JSONObject) {
            json = (JSONObject) params;
            command = JsonMapper.fromJson(json.toString(), ConsigneeAddressCommand.class);
            int pageNo = 1, pageSize = 10; // 分页参数
            if (ValidateUtil.isExistValue(json, "pageParams")) {
                JSONObject pageParam = json.getJSONObject("pageParams");
                if (ValidateUtil.isExistValue(pageParam, "pageNo")) {
                    pageNo = pageParam.getIntValue("pageNo") == 0 ? 1 : pageParam.getIntValue("pageNo");
                }
                if (ValidateUtil.isExistValue(pageParam, "pageSize")) {
                    pageSize = pageParam.getIntValue("pageSize");
                }
            }
            searchable.setPage(pageNo - 1, pageSize);
        } else {
            logger.info("JSON格式错误: {}", json);
            throw new ApiException(ErrorCode.ILLEGAL_JSON_STRING);
        }
        command.setSearchable(searchable);
        command.setCtx(CommandContext.getContext());
        command.setUserId(Long.parseLong(CommandContext.getContext().getUserId()));
        Page<ConsigneeAddress> addresses = consigneeAddressService.find(command);

        // 根据仓库Code获取仓库Id
        if (addresses != null && addresses.getContent() != null && !addresses.getContent().isEmpty()) {
            for (int i = 0; i < addresses.getContent().size(); i++) {
                if (StringUtils.isNotBlank(addresses.getContent().get(i).getOverseaWarehouse())) {
                    WarehouseCommand warehouseCommand = new WarehouseCommand();
                    warehouseCommand.setValue(addresses.getContent().get(i).getOverseaWarehouse());
                    List<Warehouse> warehouses = warehouseService.getWarehouseList(warehouseCommand);
                    if (warehouses != null && !warehouses.isEmpty()) {
                        addresses.getContent().get(i).setOverseaWarehouseId(warehouses.get(0).getWarehouseId());
                    }
                }
            }
        }
        Map<String, Object> data = new HashMap<String, Object>();
        Map<String, Object> page = new HashMap<String, Object>();
        if (null != addresses) {
            page.put("pageNo", addresses.getPageable().getPageNumber() + 1);
            page.put("pageSize", addresses.getPageable().getPageSize());
            page.put("totalCount", addresses.total);
            data.put("list", addresses.content);
        }
        data.put("pageParams", page);
        responseMsg.setData(data);
        return SUCCESS;
    }

    /**
     * 根据Code和用户ID查询，单个
     * 
     * @param requestMsg
     * @param responseMsg
     * @return
     */
    @RequestMapping(value = "/get")
    public String get(@ModelAttribute RequestMsg requestMsg, @ModelAttribute ResponseMsg responseMsg) {
        ConsigneeAddressCommand command = new ConsigneeAddressCommand();
        Object params = requestMsg.getData();
        JSONObject json = null;
        if (params instanceof JSONObject) {
            json = (JSONObject) params;
            ValidateUtil.validMaxLength(json, "code", 64, true);
            command = JsonMapper.fromJson(json.toString(), ConsigneeAddressCommand.class);
        } else {
            logger.info("JSON格式错误：{}", json);
            throw new ApiException(ErrorCode.ILLEGAL_JSON_STRING);
        }
        ConsigneeAddress address = consigneeAddressService.get(command.getId());
        Map<String, Object> data = new HashMap<String, Object>();
        data.put("address", address);
        responseMsg.setData(data);
        return SUCCESS;
    }

    /**
     * 设置默认地址
     * 
     * @param requestMsg
     * @param responseMsg
     * @return
     */
    @RequestMapping(value = "/default")
    public String setDefault(@ModelAttribute RequestMsg requestMsg, @ModelAttribute ResponseMsg responseMsg) {
        Object params = requestMsg.getData();
        JSONObject json = null;
        if (params instanceof JSONObject) {
            json = (JSONObject) params;
            ValidateUtil.validMaxLength(json, "code", 64, true);
        } else {
            logger.info("JSON格式错误: {}", json);
            throw new ApiException(ErrorCode.ILLEGAL_JSON_STRING);
        }
        ConsigneeAddressCommand command = JsonMapper.fromJson(json.toString(), ConsigneeAddressCommand.class);
        ConsigneeAddress address = consigneeAddressService.get(command.getId());
        if (address == null) {
            logger.info("地址不存在: {}", command.getId());
            throw new ApiException(ErrorCode.CONSIGNEE_ADDRESS_NOT_EXISIT, command.getId());
        }

        // 校验该记录是否属于当前用户
        long userId = Long.parseLong(CommandContext.getContext().getUserId());
        if (userId != address.getUserId()) {
            logger.info("地址不属于本人，不允许设置: {}", command);
            throw new ApiException(ErrorCode.RECORD_NOT_BELONG_CURRENT_USER, command.getId());
        }
        command.setUserId(userId);
        consigneeAddressService.setDefault(command);
        return SUCCESS;
    }

    /**
     * 校验国家名称，并设置countryCode
     * 
     * @param command
     * @return
     */
    private boolean validateAndGetCountryCode(ConsigneeAddressCommand command) {
        Country country = countryService.getCountryByCodeOrName(command.getCountryName());
        if (country == null) {
            return false;
        } else {
            command.setCountryCode(country.getCountryCode());
            command.setCountryName(country.getCountryName());
            return true;
        }
    }

    /**
     * 校验添加地址接口参数基本特性
     * 
     * @param json
     */
    private void validateAddParams(JSONObject json) {
        ValidateUtil.validImportMaxLength(json, "code", "code", 64, true);
        ValidateUtil.validImportMaxLength(json, "source", "数据来源", 8, true);
        ValidateUtil.validImportMaxLength(json, "warehouseName", "仓库名称", 100, true);
        ValidateUtil.validImportMaxLength(json, "countryCode", "国家code", 32, true);
        ValidateUtil.validImportMaxLength(json, "countryName", "国家名称", 50, true);
        ValidateUtil.validImportMaxLength(json, "stateName", "州/省", 100, true);
        ValidateUtil.validImportMaxLength(json, "cityName", "城市", 50, true);
        ValidateUtil.validImportMaxLength(json, "detail1", "街道1", 100, true);
        ValidateUtil.validImportMaxLength(json, "detail2", "街道2", 100, false);
        ValidateUtil.validImportMaxLength(json, "doorplate", "门牌号", 64, false);
        ValidateUtil.validImportMaxLength(json, "postcode", "邮编", 64, true);
        ValidateUtil.validImportMaxLength(json, "contactPerson", "联系人", 30, true);
        ValidateUtil.validImportMaxLength(json, "status", "状态", 4, true);
        ValidateUtil.validImportMaxLength(json, "type", "类型", 4, true);
        // 校验是否存在特殊字符
        if (!json.getString("contactPerson").matches("[^@#￥$%&(){}<>]{0,}")) {
            throw new ApiException(ErrorCode.NOT_INPUT_SPECHARS, "联系人");
        }
        ValidateUtil.validImportMaxLength(json, "contactNumber", "联系电话", 20, true);
        ValidateUtil.validImportMaxLength(json, "email", "Email", 50, false);

    }

    /**
     * 校验新增收货地址参数逻辑正确性
     * 
     * @param command
     */
    private void validateAddCommand(ConsigneeAddressCommand command) {
        if (!validateAndGetCountryCode(command)) {
            logger.info("国家编码错误: {}", command.getCountryCode());
            throw new ApiException(ErrorCode.COUNTRY_VALUE_ERROR);
        }
        command.setCtx(CommandContext.getContext());
        command.setUserId(Long.parseLong(CommandContext.getContext().getUserId()));
        if (null == command.getUserId()) {
            logger.info("用户id为空");
            throw new ApiException(ErrorCode.FIELD_NOT_NULL, "UserID");
        } else {
            if (StringUtils.isEmpty(command.getCode())) {
                logger.info("地址Code为空");
                throw new ApiException(ErrorCode.FIELD_NOT_NULL, "Code");
            }
        }
        if (StringUtils.isNotBlank(command.getEmail())) {
            String str = "^([a-zA-Z0-9]*[-_]?[a-zA-Z0-9]+)*@([a-zA-Z0-9]*[-_]?[a-zA-Z0-9]+)+[\\.][A-Za-z]{2,3}([\\.][A-Za-z]{2})?$";
            Pattern p = Pattern.compile(str);
            Matcher m = p.matcher(command.getEmail());
            if (!m.matches()) {
                logger.info("邮箱格式错误: {}", str);
                throw new ApiException(ErrorCode.CONSIGNEE_ADDRESS_ERROR_EMAIL);
            }
        }
        if (StringUtils.isNotBlank(command.getSource())) {
            if (!command.getSource().equals(EnumConstant.AddressSource.SEL.getSource())) {
                logger.info("数据来源错误错误: {}", command.getSource());
                throw new ApiException(ErrorCode.CONSIGNEE_ADDRESS_SOURCE_INVALID, command.getSource());
            }
        }
        if (StringUtils.isNotBlank(command.getType())) {
            if (!command.getType().equals(EnumConstant.AddressType.CUS.getType())) {
                logger.info("地址类型错误: {}", command.getType());
                throw new ApiException(ErrorCode.CONSIGNEE_ADDRESS_SOURCE_INVALID, command.getType());
            }
        }
    }

    /**
     * 校验修改地址接口参数
     * 
     * @param json
     */
    private void validateUpdateParams(JSONObject json) {
        ValidateUtil.validImportMaxLength(json, "code", "code", 64, true);
        ValidateUtil.validImportMaxLength(json, "source", "数据来源", 8, true);
        ValidateUtil.validImportMaxLength(json, "warehouseName", "仓库名称", 100, false);
        ValidateUtil.validImportMaxLength(json, "countryCode", "国家code", 32, false);
        ValidateUtil.validImportMaxLength(json, "countryName", "国家名称", 50, false);
        ValidateUtil.validImportMaxLength(json, "stateName", "州/省", 100, false);
        ValidateUtil.validImportMaxLength(json, "cityName", "城市", 50, false);
        ValidateUtil.validImportMaxLength(json, "detail1", "街道1", 100, false);
        ValidateUtil.validImportMaxLength(json, "detail2", "街道2", 100, false);
        ValidateUtil.validImportMaxLength(json, "doorplate", "门牌号", 64, false);
        ValidateUtil.validImportMaxLength(json, "postcode", "邮编", 64, false);
        ValidateUtil.validImportMaxLength(json, "contactPerson", "联系人", 30, false);
        ValidateUtil.validImportMaxLength(json, "status", "状态", 4, false);
        ValidateUtil.validImportMaxLength(json, "type", "类型", 4, false);
        // 校验是否存在特殊字符
        if (!json.getString("contactPerson").matches("[^@#￥$%&(){}<>]{0,}")) {
            throw new ApiException(ErrorCode.NOT_INPUT_SPECHARS, "联系人");
        }
        ValidateUtil.validImportMaxLength(json, "contactNumber", "联系电话", 20, false);
        ValidateUtil.validImportMaxLength(json, "email", "Email", 50, false);
    }

    /**
     * 校验修改地址接口参数逻辑
     * 
     * @param json
     */
    private void validateUpdateCommand(ConsigneeAddressCommand command) {
        // 如果数据来源不是卖家，则不更新
        if (StringUtils.isNotBlank(command.getSource())) {
            if (!command.getSource().equals(EnumConstant.AddressSource.SEL.getSource())) {
                logger.info("数据来源错误错误: {}", command.getSource());
                throw new ApiException(ErrorCode.CONSIGNEE_ADDRESS_SOURCE_INVALID, command.getSource());
            }
        }
        command.setCtx(CommandContext.getContext());
        ConsigneeAddress address = consigneeAddressService.get(command.getId());
        // 若地址不存在，则不更新
        if (address == null) {
            logger.info("地址不存在: {}", command);
            throw new ApiException(ErrorCode.CONSIGNEE_ADDRESS_NOT_EXISIT, command.getId());
        }

        // 校验该记录是否属于当前用户
        long userId = Long.parseLong(CommandContext.getContext().getUserId());
        if (userId != address.getUserId()) {
            logger.info("地址不属于本人，不允许修改: {}", command);
            throw new ApiException(ErrorCode.RECORD_NOT_BELONG_CURRENT_USER, command.getId());
        }

        if (!address.getCode().equals(command.getCode())) {
            logger.info("地址code不允许修改: {}", command);
            throw new ApiException(ErrorCode.CONSIGNEE_ADDRESS_CODE_NOTUPDATE, command.getCode());
        }

        if (!validateAndGetCountryCode(command)) {
            logger.info("国家编码错误: {}", command);
            throw new ApiException(ErrorCode.COUNTRY_VALUE_ERROR);
        }
        // 如果仅仅修改联系人，联系电话，邮件地址，则状态不用更改
        if (onlyContactInfoChange(command, address)) {
            command.setStatus(address.getStatus());
        } else {
            command.setStatus(EnumConstant.AddressStatus.WFC.getStatus()); // 修改后设置状态为待审核
        }
    }

    /**
     * 只有联系人信息有改动
     * 
     * @param command
     * @param address
     * @return
     */
    private boolean onlyContactInfoChange(ConsigneeAddressCommand command, ConsigneeAddress address) {
        if (notEmptyAndEqual(command.getWarehouseName(), address.getWarehouseName())
            && notEmptyAndEqual(command.getStateName(), address.getStateName())
            && notEmptyAndEqual(command.getCityName(), address.getCityName())
            && notEmptyAndEqual(command.getDetail1(), address.getDetail1())
            && notEmptyAndEqual(command.getDetail2(), address.getDetail2())
            && notEmptyAndEqual(command.getDoorplate(), address.getDoorplate())
            && notEmptyAndEqual(command.getPostcode(), address.getPostcode())
            && (StringUtils.isEmpty(command.getCountryName()) || (StringUtils.isNotEmpty(command.getCountryName()) && StringUtils.equalsIgnoreCase(command.getCountryName(),
                address.getCountryName())))) {
            return true;
        }
        return false;
    }

    /**
     * command里的值为空，或command里的值不为空并且等于
     * 
     * @param commandVal
     * @param voVal
     * @return
     */
    private boolean notEmptyAndEqual(String commandVal, String voVal) {
        if (StringUtils.isEmpty(commandVal)) {
            return true;
        }
        if (StringUtils.isNotEmpty(commandVal) && StringUtils.equals(commandVal, voVal)) {
            return true;
        }
        return false;
    }

}
